﻿#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

#endregion

namespace NDaisy.Core
{
    /// <summary>
    ///     Engine
    /// </summary>
    public abstract class WorkEngine
    {
        /// <summary>
        ///     Run startup tasks
        /// </summary>
        protected virtual void RunStartupTasks(params string[] assemblyNames)
        {
              
            var startUpTaskTypes =GetTypeByAsemmbly(assemblyNames);
            var startUpTasks =
               startUpTaskTypes.Select(startUpTaskType => (IStartupTask)Activator.CreateInstance(startUpTaskType))
                   .ToList();
            
            startUpTasks = startUpTasks.OrderBy(st => st.Order).ToList();
            foreach (var startUpTask in startUpTasks)
                startUpTask.Execute();
        }

        private IEnumerable<Type> GetTypeByAsemmbly(params string[] assemblyNames)
        {
            var types=new List<Type>();
            foreach (var assemblyName in assemblyNames)
            {
                
                var startUpTaskTypes = Assembly.Load(new AssemblyName(assemblyName)).DefinedTypes
            .Where(d => typeof(IStartupTask).IsAssignableFrom(d.DeclaringType))
            .Select(d => d.DeclaringType);
                
                types.AddRange(startUpTaskTypes);
            }
            return types;
        }


          

        /// <summary>
        ///     Runs the aysnc startup tasks.
        /// </summary>
        protected virtual void RunAysncStartupTasks()
        {
            var startUpTasks = ResolveAll<IAsyncStartupTask>().ToList();
             
            Parallel.ForEach(startUpTasks, d => d.Execute());
        }


        /// <summary>
        ///     Register dependencies
        /// </summary
        public abstract void RegisterDependencies();

        public abstract string[] GetTaskAssembly();
        #region Methods

        /// <summary>
        ///     初始化
        /// </summary>
        public virtual void Initialize()
        {
            RegisterDependencies();

            RunStartupTasks(GetTaskAssembly());
            RunAysncStartupTasks();
        }


        /// <summary>
        ///     Resolve dependencies
        /// </summary>
        /// <typeparam name="T">T</typeparam>
        /// <returns></returns>
        private T[] ResolveAll<T>()
        {
            return ServiceLocator.ServiceLocator.Current.GetAllInstances<T>().ToArray();
        }

        #endregion
    }
}